package hr.fer.zpr.nmbp.project3.dao;

import hr.fer.zpr.nmbp.project3.dao.exceptions.DAOException;
import hr.fer.zpr.nmbp.project3.dao.exceptions.PrimaryKeyConstraintException;
import hr.fer.zpr.nmbp.project3.dao.util.ObjectFromXMLGen;
import hr.fer.zpr.nmbp.project3.dao.util.XMLGen;
import hr.fer.zpr.nmbp.project3.model.Bolest;
import java.util.ArrayList;
import java.util.List;

import org.exist.xmldb.XQueryService;
import org.w3c.dom.Node;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;

public class BolestDAO {
	
	private XQueryService xqs;
	
	public BolestDAO(Collection col) {
		try {
			this.xqs = (XQueryService)col.getService("XQueryService", "1.0");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom");
		}
	}

	public void save(Bolest bolest) {
		if (bolest.getNaziv() == null || bolest.getNaziv().isEmpty()) {
			throw new PrimaryKeyConstraintException(
					"Naziv bolesti je obavezan");
		}
		
		// Update bolesti ako postoji u bazi
    	try {
			if(this.exists(bolest)) {
				this.update(bolest);
				return;
			}
    	
	    	// Generiraj novu sifru ako ju nema
	    	if(bolest.getSifra() == 0){
	    		bolest.setSifra(this.generateNextSifra());
	    	}
    	
    		// Spremanje nove bolesti u bazu
			xqs.query("update insert " + XMLGen.getXML(bolest) + "into /ebolnica/bolesti");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
	}

	private int generateNextSifra() {
    	int nextSifra;
    	try {
    		ResourceSet resSet = xqs.query("let $res := /ebolnica/bolesti/bolest/@sifra return " +
    				"<nextid>{ if (count($res) > 0) then max($res)+1 else 0+1 }</nextid>");
			Node node = (Node)((XMLResource)resSet.getIterator().nextResource()).getContentAsDOM();
			nextSifra = Integer.parseInt(node.getNodeValue());
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
    	
    	return nextSifra;
	}

	private void update(Bolest bolest) {
		// Ažuriranje bolesti
    	try {
			xqs.query("update replace /ebolnica/bolesti/bolest[@sifra=" + bolest.getSifra() + "] with " + 
					XMLGen.getXML(bolest));
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
	}

	private boolean exists(Bolest bolest) throws XMLDBException {
    	ResourceSet set = xqs.query("/ebolnica/bolesti/bolest[@sifra="+bolest.getSifra()+"]");
    	if(set.getSize() > 0){
    		return true;
    	}else{
    		return false;
    	}
	}

	public void delete(final Bolest bolest) {
		// Brisanje bolesti
    	try {
			xqs.query("update delete /ebolnica//dijagnozaBolest[@bolest=" + bolest.getSifra() + "]");
			xqs.query("update delete /ebolnica/bolesti/bolest[@sifra=" + bolest.getSifra() + "]");
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}    	
   	}

	public List<Bolest> load(Bolest bolestPrototype) {
		List<Bolest> allBolesti = this.loadAll();
    	List<Bolest> filteredBolnice = new ArrayList<Bolest>();
    	
    	for(Bolest bolest : allBolesti){
    		if(bolest.getSifra() == bolestPrototype.getSifra()){
    			filteredBolnice.add(bolest);
    		}
    	}
    	
    	return filteredBolnice;
	}

	public List<Bolest> loadAll() {
		ArrayList<Bolest> loadedBolesti = new ArrayList<Bolest>();
    	
    	// Učitavanje bolesti
    	try {
    		ResourceSet resSet = xqs.query("/ebolnica/bolesti/bolest");

    		ResourceIterator iter = resSet.getIterator();
			while(iter.hasMoreResources()){
				XMLResource res = (XMLResource) iter.nextResource();
				Bolest tempBolest = (Bolest)ObjectFromXMLGen.createInstance(res.getContentAsDOM());
				if(tempBolest != null){
					loadedBolesti.add(tempBolest);
				}
			}
		} catch (XMLDBException e) {
			throw new DAOException("Greška u radu s bazom!");
		}
    	
    	return loadedBolesti;
	}
}
